import {action, reaction} from "./ai";

export const Status = {stop: 0, wait: 1, playing: 2, checking: 3};
export const CheckDiscardType = {peng: '碰', chi: '吃', gang: '杠', hu: '胡'};
/**
 * 麻将子
 * @param label 牌面
 * @param order 顺序
 * @param type 类型
 */
export const Tile = function (label, order, type) {

    return {
        label,
        order,
        type,
        sameTo(tile){
            return this.order === tile.order && this.type === tile.type;
        },
        /**
         * 是下一张牌
         */
        nextTo(tile){
            return this.type === tile.type && this.order === tile.order + 1;
        },
        /**
         * 是前一张牌
         */
        prevTo(tile){
            return this.type === tile.type && this.order === tile.order - 1;
        }
    }
};
/**
 * 麻将堆
 * @returns {{}}
 * @constructor
 */
export const Pile = function () {
    let tiles = [];
    //三种基本花色
    let types = ['条', '筒', '万'];
    for (let type of types) {
        // 9 个数字
        for (let i = 1; i <= 9; i++) {
            //每个牌型4个
            for (let n = 0; n < 4; n++) {
                tiles.push(new Tile(i + type, i, type));
            }
        }
    }

    return {
        tiles,
        /**
         * 洗牌
         */
        shuffle(){
            tiles.sort(() => 0.5 - Math.random());
        },
        /**
         * 取出第一张牌
         */
        shift(){
            return tiles.shift()
        }
    }
};

/**
 * 玩家
 * @returns {{tiles: Array}}
 * @constructor
 */
export const Gamer = function (index) {
    return {
        index,
        /**
         * 手牌
         */
        tiles: [],
        /**
         * 碰，吃，杠的牌
         */
        otherTiles:[],
        status: [],
        checked: [],
        drawingTile: new Tile(),
        /**
         * 整理手牌
         */
        sort(){
            action.sort(this.tiles);
        },
        /**
         * 摸牌
         */
        draw(pile){
            this.drawingTile = pile.shift();
        },
        /**
         * 直接打出摸起来的牌
         */
        discardDraw(deck){
            deck.discard(this.drawingTile);
            this.drawingTile = new Tile();
        },
        /**
         * 出牌
         */
        discard(index, deck){
            deck.discard(this.tiles.splice(index, 1)[0]);
            this.tiles.push(this.drawingTile);
            this.sort();
            this.drawingTile = new Tile();
        },
        clearChecked(){
            this.checked = [];
        },
        /**
         * 检查对打出的牌的反应, exclude排除检查项目
         */
        checkDiscard(tile, exclude = []){
            if (exclude.indexOf(CheckDiscardType.peng) === -1 && reaction.canPeng(tile, this.tiles)) {
                this.checked.push(CheckDiscardType.peng);
            }
            if (exclude.indexOf(CheckDiscardType.chi) === -1 && reaction.canChi(tile, this.tiles)) {
                this.checked.push(CheckDiscardType.chi);
            }
            if (exclude.indexOf(CheckDiscardType.gang) === -1 && reaction.canGang(tile, this.tiles)) {
                this.checked.push(CheckDiscardType.gang);
            }
            if (exclude.indexOf(CheckDiscardType.hu) === -1 && reaction.canHu(tile, this.tiles)) {
                this.checked.push(CheckDiscardType.hu);
            }
            this.checked.sort((a, b) => a.localeCompare(b));
        },
        reaction(checkedType,deck){
            if(checkedType===CheckDiscardType.peng){
                this.peng(deck)
            }
        },
        /**
         * 碰牌
         */
        peng(deck){
            let tile = deck.discardingTile;
            let pengs = reaction.canPeng(tile,this.tiles);
            //如果执行碰
            if(pengs){
                let sequence = [tile];
                for(let i of pengs){
                    sequence.push(this.tiles.splice(i,1)[0]);
                }
                this.otherTiles.push(sequence);
                deck.skipTo(this.index);
            }
        }
    }
};

/**
 * 麻将桌
 */
export const Deck = function () {
    //生成牌组
    let pile = new Pile();
    pile.shuffle();
    let gamers = [];
    //初始化玩家
    let gamerSize = 4;
    for (let i = 0; i < gamerSize; i++) {
        gamers.push(new Gamer(i));
    }
    return {
        /**
         * 游戏状态
         */
        status: Status.stop,
        countdown: 0,
        countdownId: 0,
        countdownMax: 5000,
        //庄
        boss: gamers[0],
        //当前
        currentIndex: 0,
        gamers,
        pile,
        /**
         * 当前正在打出的牌
         */
        discardingTile: new Tile(),
        /**
         * 已经出过的牌
         */
        trash: [],
        /**
         * 发牌,默认13张
         */
        deal(n = 13){
            for (let gamer of gamers) {
                for (let i = 0; i < n; i++) {
                    gamer.tiles.push(pile.shift());
                }
                gamer.sort();
            }
        },
        /**
         * 出牌
         */
        discard(tile){
            //当前玩家出牌
            this.discardingTile = tile;
            //其余玩家响应
            this.wait(() => {
                this.discarded();
            });
            this.checkDiscard();
        },
        discarded(){
            this.gamers.forEach((gamer) => {
                gamer.clearChecked();
            });
            this.trash.push(this.discardingTile);
            this.discardingTile = new Tile();
            this.next();
        },
        /**
         * 其余玩家检查棋牌,只有下家能吃
         */
        checkDiscard(){
            this.status = Status.checking;
            for (let i = 0; i < this.gamers.length; i++) {
                //非下家的其余玩家
                if (i !== this.currentIndex && i !== (this.currentIndex + 1) % this.gamers.length) {
                    let gamer = this.gamers[i];
                    gamer.checkDiscard(this.discardingTile,[CheckDiscardType.chi]);
                }
                //下家
                if (i === (this.currentIndex + 1) % this.gamers.length) {
                    let gamer = this.gamers[i];
                    gamer.checkDiscard(this.discardingTile);
                }
            }
        },
        clearChecked(){
            this.gamers.forEach((gamer)=>gamer.clearChecked());
        },
        wait(action){
            this.countdown = this.countdownMax;
            //每0.5秒检测,15秒后没有响应,当前玩家为下家
            this.countdownId = setInterval(() => {
                this.countdown -= 500;
                this.countdown = Math.max(this.countdown, 0);
                if (this.countdown <= 100) {
                    action();
                    this.resume();
                }
            }, 500);
        },
        resume(){
            this.status = Status.playing;
            clearInterval(this.countdownId);
            this.countdown=this.countdownMax;
            this.clearChecked();
        },
        start(){
            if(this.status===Status.stop) {
                this.status = Status.playing;
                this.pile.shuffle();
                this.deal(13);
                this.gamers[this.currentIndex].draw(this.pile);
            }

        },
        next(){
            this.currentIndex = (this.currentIndex + 1) % this.gamers.length;
            this.gamers[this.currentIndex].draw(this.pile);
        },
        skipTo(gamerIndex){
            this.currentIndex = gamerIndex;
            this.resume();
        }

    }
};

